﻿using DocumentFormat.OpenXml.Experimental;
using DocumentFormat.OpenXml.Packaging;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;


namespace DataService.Office.Word
{
    public class XmlPart
    {

        public static void MovePartFromSourceToTarget(Package sourecePackage, Package targetPackage, List<string> noMoveList)
        {
            var list = sourecePackage.GetParts();
            foreach (var item in list)
            {
                if (targetPackage.PartExists(item.Uri))
                {
                    continue;
                }
                string tempUri = item.Uri.ToString();
                var tempArray = tempUri.Split('/');
                if (noMoveList.Count > 0)
                {
                    int tempCount = tempUri.Split('/').Count(x => noMoveList.Contains(x));
                    if (tempCount > 0)
                    {
                        continue;
                    }
                }
                if (tempUri.Contains("document.xml") || tempUri.Contains("media"))
                {
                    continue;
                }
                Console.WriteLine(item.Uri + "******" + item.ContentType);
                System.IO.Packaging.PackagePart newPart = targetPackage.CreatePart(item.Uri, item.ContentType, System.IO.Packaging.CompressionOption.Normal);
                //FileStream ifs = new FileStream(imageUrl, FileMode.Open, FileAccess.Read);
                using (StreamReader streamReader = new StreamReader(item.GetStream()))
                {
                    using (StreamWriter streamWriter = new StreamWriter(newPart.GetStream(FileMode.Create)))
                    {
                        streamWriter.Write(streamReader.ReadToEnd());
                    }
                }
                //这种无法创建文件,优化的时候在看这里，先使用上面的StreamWriter绘制文件
                //using (Stream partStream = newPart.GetStream(FileMode.Create, FileAccess.Write))
                //{
                //    byte[] byteTmp = new byte[1024];
                //    int count = 0;
                //    while ((count = item.GetStream().Read(byteTmp, 0, 1024)) > 0)
                //    {
                //        partStream.Write(byteTmp, 0, count);
                //    }
                //}
            }
        }

        public static void MovePartFromSourceToTarget(WordprocessingDocument soureceWordprocessingDocument, Package targetPackage, List<string> noMoveDirList, List<string> noMoveFileList)
        {
            var list = soureceWordprocessingDocument.GetPackage().GetParts();
            foreach (var item in list)
            {
                if (targetPackage.PartExists(item.Uri))
                {
                    continue;
                }
                string tempUri = item.Uri.ToString();
                var tempArray = tempUri.Split('/');
                if (noMoveDirList.Count > 0)
                {
                    int tempCount = tempArray.Count(x => noMoveDirList.Contains(x));
                    if (tempCount > 0)
                    {
                        continue;
                    }
                }
                if (noMoveFileList.Count > 0)
                {
                    string fileName = tempArray[tempArray.Length - 1];
                    int tempCount1 = noMoveFileList.Count(x => fileName.Contains(x));
                    if (tempCount1 > 0)
                    {
                        continue;
                    }
                }
                string partName = tempArray[tempArray.Length - 1];
                if (partName == "document.xml" || tempUri.Contains("media"))
                {
                    continue;
                }

                System.IO.Packaging.PackagePart newPart = targetPackage.CreatePart(item.Uri, item.ContentType, System.IO.Packaging.CompressionOption.Normal);
                //FileStream ifs = new FileStream(imageUrl, FileMode.Open, FileAccess.Read);
                using (StreamReader streamReader = new StreamReader(item.GetStream(FileMode.Open,FileAccess.Read)))
                {
                    using (StreamWriter streamWriter = new StreamWriter(newPart.GetStream(FileMode.Create)))
                    {
                        streamWriter.Write(streamReader.ReadToEnd());
                    }
                }
                //这种无法创建文件,优化的时候在看这里，先使用上面的StreamWriter绘制文件
                //using (Stream partStream = newPart.GetStream(FileMode.Create, FileAccess.Write))
                //{
                //    byte[] byteTmp = new byte[1024];
                //    int count = 0;
                //    while ((count = item.GetStream().Read(byteTmp, 0, 1024)) > 0)
                //    {
                //        partStream.Write(byteTmp, 0, count);
                //    }
                //}
            }
        }

        /// <summary>
        /// 移动根目录下文件夹和文件
        /// word文件夹下除外
        /// </summary>
        /// <param name="soureceWordprocessingDocument"></param>
        /// <param name="targetPackage"></param>
        /// <param name="noMoveDirList"></param>
        /// <param name="noMoveFileList"></param>
        public static void MoveRootPartFromSourceToTarget(Package sourecePackage, Package targetPackage, List<string> noMoveDirList, List<string> noMoveFileList)
        {
            var list = sourecePackage.GetParts();
            foreach (var item in list)
            {
                if (targetPackage.PartExists(item.Uri))
                {
                    continue;
                }
                string tempUri = item.Uri.ToString();
                var tempArray = tempUri.Split('/');
                if (noMoveDirList.Count > 0)
                {
                    int tempCount = tempArray.Count(x => noMoveDirList.Contains(x));
                    if (tempCount > 0)
                    {
                        continue;
                    }
                }
                if (noMoveFileList.Count > 0)
                {
                    string fileName = tempArray[tempArray.Length - 1];
                    int tempCount1 = noMoveFileList.Count(x => fileName.Contains(x));
                    if (tempCount1 > 0)
                    {
                        continue;
                    }
                }
                string partName = tempArray[1];
                if (partName.ToLower() == "word")
                {
                    continue;
                }
                System.IO.Packaging.PackagePart newPart = targetPackage.CreatePart(item.Uri, item.ContentType, System.IO.Packaging.CompressionOption.Normal);
                //FileStream ifs = new FileStream(imageUrl, FileMode.Open, FileAccess.Read);
                using (StreamReader streamReader = new StreamReader(item.GetStream()))
                {
                    using (StreamWriter streamWriter = new StreamWriter(newPart.GetStream(FileMode.Create)))
                    {
                        streamWriter.Write(streamReader.ReadToEnd());
                    }
                }
            }
        }

        /// <summary>
        ///移动word文件夹下文件如【word/media/image23.jpeg】,根据【_Rels】文件夹下所有对应关系，将源文件的部件移动到目标文件中
        /// 备注：只移动document.xml.rels关系关联的部件,只移动该文件需要的部件
        /// 思路：遍历【_Rels】文件夹下的所有【XXXXXX.xml.rels】,取出文件的关联关系
        /// 【document.xml.rels】不处理
        /// </summary>
        /// <param name="sourceProcessingDocument"></param>
        /// <param name="targetProcessingDocument"></param>
        /// <param name="uriList"></param>
        public static void MovePartFileFromSourceToTargetByRels(Package sourcePackage, Package targetPackage, List<Uri> uriList)
        {
             var eeee = Package.Open("filename", FileMode.Open, FileAccess.ReadWrite);

            if (uriList == null || uriList.Count == 0) return;
            //1.先使用目标targetPackage遍历/word/_rels下的路径
            foreach (var item in uriList)
            {
                if (!targetPackage.PartExists(item)) continue;
                var packagePart = targetPackage.GetPart(item);
                string[] tempArray = item.ToString().Split('/');
                string partFileName = tempArray[tempArray.Length - 1];
                XmlDocument newWordRelsXmlDocument = XmlPackagePart.GetXmlDocumentByPartName(targetPackage, partFileName);
                XmlPart.MovePartFromSourceToTarget(sourcePackage, targetPackage, newWordRelsXmlDocument);
            }

        }

        /// <summary>
        ///移动word文件夹下文件如【word/media/image23.jpeg】,根据document.xml.rels对应关系，将源文件的部件移动到目标文件中
        /// 备注：只移动document.xml.rels关系关联的部件,只移动该文件需要的部件
        /// </summary>
        /// <param name="soureceWordprocessingDocument"></param>
        /// <param name="targetPackage"></param>
        /// <param name="targetXML">目标文件的document.xml.rels结构</param>
        public static void MovePartFromSourceToTarget(Package sourcePackage, Package targetPackage, XmlDocument targetXML)
        {
            //先获取源文件的所有部件集合
        
            //遍历document.xml.rels的XMl中的Relationship节点集合，通过Id找到Target对应的文件路径然后通过路径从源文件中复制到目标文件中
            XmlNode xmlNode = targetXML.ChildNodes[1];
            XmlNodeList xmlNodeList = xmlNode.ChildNodes;
            string relativeRoot = "/word/";
            #region 原来读取图片的方式
            //IEnumerable<ImagePart> soureceImagePartList = soureceWordprocessingDocument.MainDocumentPart.ImageParts;
            //Dictionary<string, ImagePart> keyValuePairsImagePart = new Dictionary<string, ImagePart>();
            //foreach (var item in soureceImagePartList)
            //{
            //    string relationShipId = soureceWordprocessingDocument.MainDocumentPart.GetIdOfPart(item);
            //    keyValuePairsImagePart[relationShipId] = item;
            //}
            #endregion

            foreach (XmlNode item in xmlNodeList)
            {
                //得到关联文件如Target="media/image618.png"、Target="diagrams/drawing22.xml"等这样的数据
                #region 取出目标文件的document.xml.rels值
                string targetVal = item.Attributes["Target"].Value;
                string targetRelationShipId = item.Attributes["Id"].Value;
                string targetType = item.Attributes["Type"].Value;
                #endregion
                #region 验证多媒体类型
                //1.验证超链接
                if (targetType == XmlPackageConst.hyperlinkNamespace)
                {
                    continue;
                }
                //2.验证是否外部资源
                //示例：<Relationship Target="../../../../ADMINI~1/AppData/Local/Temp/ksohtml11168/wps1.jpg" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Id="rId143" TargetMode="External"/> 为外部资源
                XmlAttribute xmlAttribute = item.Attributes["TargetMode"];
                if (xmlAttribute != null && xmlAttribute.Value != null && xmlAttribute.Value.ToString().Equals("External"))
                {

                    continue;
                }
                string[] tempArray = targetVal.Split('/');
                string fileName = tempArray[tempArray.Length - 1];
                if (fileName.ToLower().Equals("document.xml") || fileName.ToLower().Equals("document.xml.rels") || fileName.ToLower().Equals("numbering.xml")) continue;
                string tempUriString = string.Empty;
                if (tempArray[0] == "..")
                {
                    tempUriString = targetVal;
                    tempUriString = tempUriString.Replace("..", "");
                }
                else
                {
                    targetVal = targetVal.Replace("/word/", "");
                    targetVal = targetVal.Replace("word/", "");
                    tempUriString = relativeRoot + targetVal;
                }
                #endregion
                Uri tempUri = new Uri(tempUriString, UriKind.Relative);//如果使用相对路径需要自定义Relation关系
                if (targetPackage.PartExists(tempUri)) continue;
                if (targetVal.Contains("document.xml")) continue;
                if (!sourcePackage.PartExists(tempUri)) continue;
                #region 移动文件
                if (targetType == XmlPackageConst.imgNamespace)
                {
                    //这里可以优化，可以把移动图片的逻辑也放到这里
                    #region 移动图片至目标文件
                    int size = 1024;
                    if (sourcePackage.PartExists(tempUri) && !targetPackage.PartExists(tempUri))
                    {
                        PackagePart packagePart=sourcePackage.GetPart(tempUri);
                        Stream stream = packagePart.GetStream();
                        System.IO.Packaging.PackagePart newPart = targetPackage.CreatePart(tempUri, packagePart.ContentType, System.IO.Packaging.CompressionOption.Normal);
                        using (Stream partStream = newPart.GetStream(FileMode.Create, FileAccess.Write))
                        {
                            byte[] byteTmp = new byte[size];
                            int count = 0;
                            while ((count = stream.Read(byteTmp, 0, size)) > 0)
                            {
                                partStream.Write(byteTmp, 0, count);
                            }
                        }
                    }
                    #region 原来移动图片的逻辑
                    //if (keyValuePairsImagePart.Count > 0)
                    //{
                    //    int size = 1024;
                    //    if (!keyValuePairsImagePart.ContainsKey(targetRelationShipId)) continue;
                    //    ImagePart imagePart = keyValuePairsImagePart[targetRelationShipId];
                    //    Stream stream = imagePart.GetStream();
                    //    System.IO.Packaging.PackagePart newPart = targetPackage.CreatePart(tempUri, imagePart.ContentType, System.IO.Packaging.CompressionOption.Normal);
                    //    using (Stream partStream = newPart.GetStream(FileMode.Create, FileAccess.Write))
                    //    {
                    //        byte[] byteTmp = new byte[size];
                    //        int count = 0;
                    //        while ((count = stream.Read(byteTmp, 0, size)) > 0)
                    //        {
                    //            partStream.Write(byteTmp, 0, count);
                    //        }
                    //    }
                    //}
                    #endregion

                    #endregion
                }
                else
                {
                    PackagePart packagePart = sourcePackage.GetPart(tempUri);
                    System.IO.Packaging.PackagePart newPart = targetPackage.CreatePart(tempUri, packagePart.ContentType, System.IO.Packaging.CompressionOption.Normal);
                    using (StreamReader streamReader = new StreamReader(packagePart.GetStream()))
                    {
                        using (StreamWriter streamWriter = new StreamWriter(newPart.GetStream(FileMode.Create)))
                        {
                            streamWriter.Write(streamReader.ReadToEnd());
                        }
                    }
                }
                #endregion
            }
        }
        /// <summary>
        /// 移动【_rels】文件夹下的文件,【document.xml.rels】除外
        /// </summary>
        public static List<Uri> MoveRelsFromSourceToTarget(Package sourcePackage, Package targetPackage)
        {
            List<Uri> uriList = new List<Uri>();
            var list = sourcePackage.GetParts();
            foreach (var item in list)
            {
                if (targetPackage.PartExists(item.Uri))
                {
                    continue;
                }
                string tempUri = item.Uri.ToString();
                var tempArray = tempUri.Split('/');
                if (tempArray.Length < 3) continue;
                string partName = tempArray[tempArray.Length - 3];
                string resName = tempArray[tempArray.Length - 2];
                string resFileName = tempArray[tempArray.Length - 1];
                if (resFileName.ToLower().Equals("document.xml.rels"))
                {
                    continue;
                }
                if (partName.ToLower().Equals("word") && resName.ToLower().Equals("_rels"))
                {
                    uriList.Add(item.Uri);
                    System.IO.Packaging.PackagePart newPart = targetPackage.CreatePart(item.Uri, item.ContentType, System.IO.Packaging.CompressionOption.Normal);
                    //FileStream ifs = new FileStream(imageUrl, FileMode.Open, FileAccess.Read);
                    using (StreamReader streamReader = new StreamReader(item.GetStream()))
                    {
                        using (StreamWriter streamWriter = new StreamWriter(newPart.GetStream(FileMode.Create)))
                        {
                            streamWriter.Write(streamReader.ReadToEnd());
                        }
                    }
                }

            }
            return uriList;
        }



        /// <summary>
        ///移动word文件夹下文件如【word/media/image23.jpeg】,根据document.xml.rels对应关系，将源文件的部件移动到目标文件中
        /// 备注：只移动document.xml.rels关系关联的部件
        /// </summary>
        /// <param name="soureceWordprocessingDocument"></param>
        /// <param name="targetPackage"></param>
        /// <param name="relationShipIdList">document.xml.rels中的Id集合</param>
        /// <param name="targetXML">目标文件的document.xml.rels结构</param>
        public static void MovePartFromSourceToTargetByRelationIdList(WordprocessingDocument soureceWordprocessingDocument, XmlDocument sourceRelsXML, Package targetPackage, List<string> targetRelationIdList)
        {
            //MainDocumentPart sourceMainDocumentPart = soureceWordprocessingDocument.MainDocumentPart;
            ////遍历源文件的文件（如xml、图片、bin文件等）
            ///原版本的如果使用 OpenXmlPackage.Package，则返回的包类型不再为 System.IO.Packaging.Package，而是 DocumentFormat.OpenXml.Packaging.IPackage
            // var list = soureceWordprocessingDocument.Package.GetParts();
            var list = soureceWordprocessingDocument.GetPackage().GetParts();
            //foreach (var item in list)
            //{
            //    string relationShipId = sourceMainDocumentPart.GetIdOfPart(item);
            //}
        }
        /// <summary>
        /// 判断部件是否存在
        /// </summary>
        /// <param name="package"></param>
        /// <param name="partName">部件名称 如numbering.xml、footer1.xml等</param>
        /// <returns></returns>
        public static bool IsExistsPart(Package package,string partName)
        {
            var list = package.GetParts();
            foreach (var item in list)
            {
                string tempUri = item.Uri.ToString();
                var tempArray = tempUri.Split('/');
               string tempPartName= tempArray[tempArray.Length - 1];
                if (partName == tempPartName)
                {
                    return true;
                }
            }
            return false;
        }


    }
}
